import type { IntervalTaskProps } from '../../../../../lib/timer_manager'
import type { ImagePreview } from '../index'
import type { PreviewState } from '../types'
import { TextInput } from '../../../../../components/text_input'
import {
  ICON_COLOR,
  ICON_IDS,
} from '../../../../../lib/icons/types/constants'
import { ToolKit } from '../../../../../lib/utils/toolkit'
import { logger } from '../../../../../types/constants'
import { SYMBOLS } from '../../../../../types/interfaces'

export class ImagePreviewUIService {
  private readonly name: string = 'ImagePreviewUIService'
  private imagePreview: ImagePreview
  readonly className: string = 'image-preview-container'
  readonly targetClassName: string = 'image-preview-target'
  private readonly navigationInputId: string = 'image-preview-navigation-input'
  readonly buttonClassName: string = 'image-preview-button'
  currentPreviewIndex: number = -1
  previewElements: PreviewState[] = [] // 所有可预览的元素
  currentPreviewElement: JQuery<HTMLElement> | null = null // 当前显示的预览容器
  private textInput: TextInput | null = null
  private readonly updateDownloadTimeTask: IntervalTaskProps = {
    id: 'image-preview-update-download-time',
    interval: 1000,
    running: false,
  }

  constructor(instance: ImagePreview) {
    this.imagePreview = instance
  }

  destroy(): void {
    this.currentPreviewIndex = -1
    this.previewElements = []
    this.textInput = null
  }

  /**
   * 创建预览按钮
   */
  createPreviewButton(elementId: string): JQuery<HTMLElement> {
    const button = $(`
      <button class="${this.buttonClassName}" type="button" title="预览图片"></button>
    `)

    // 添加点击事件
    button.on(this.imagePreview.eventNames.buttonClick, async (e) => {
      e.stopPropagation()
      e.preventDefault()

      await this.handlePreviewButtonClick(elementId)

      // 切换按钮状态
      const $button = $(e.currentTarget)
      $button.addClass('active')
    })

    return button
  }

  /**
   * 处理预览按钮点击
   */
  private async handlePreviewButtonClick(elementId: string): Promise<void> {
    const state = this.imagePreview.previewStates.get(elementId)

    this.removePreview()

    if (!state)
      return

    // 设置当前预览索引
    this.currentPreviewIndex = this.previewElements.findIndex(item => item === state)

    // 显示预览
    await this.showPreview(state)
  }

  /**
   * 显示图片预览
   */
  private async showPreview(state: PreviewState): Promise<void> {
    const { imageUrl, title } = state

    // 获取图片信息
    state.imageInfo = await this.imagePreview.getImageMetadata(imageUrl)

    /// 创建或更新预览元素
    if (!this.currentPreviewElement) {
      // 首次创建预览容器
      this.currentPreviewElement = this.createPreviewElement()
      $('body').append(this.currentPreviewElement)
    }

    // 更新预览内容
    this.updatePreviewContent(state)

    // 更新导航状态
    this.updateNavigationState()

    logger.info(`[${this.name}] 显示图片预览: ${title}`)
  }

  /**
   * 创建预览容器（只创建一次）
   */
  private createPreviewElement(): JQuery<HTMLElement> {
    this.textInput = this.renderTextInput()

    const previewElement = $(`
      <div class="${this.className}">
        <div class="image-preview-header">
          <div class="image-preview-title-group">
            <h2 class="image-preview-title"></h2>
            <div class="image-preview-path"></div>
          </div>
          <div class="image-preview-toolbar">
            <button class="image-preview-download" title="下载图片">
              ${SYMBOLS.UI.DOWNLOAD}
            </button>
            <button class="image-preview-download-all" title="下载全部图片">
              ${SYMBOLS.UI.PACKAGE}
            </button>
            <button class="image-preview-close" title="关闭预览">
              ${SYMBOLS.UI.CLOSE}
            </button>
          </div>
        </div>
        
        <div class="image-preview-content">
          <div class="image-preview-image-container">
            <div class="image-preview-loading">加载中...</div>
            <img class="image-preview-img" style="display: none;" alt="图片预览">
          </div>
        </div>
        
        <div class="image-preview-path-container">
          <span class="path-info"></span>
        </div>
        
        <div class="image-preview-info">
          <div class="image-info-item">
            <span class="info-value size-info"></span>
          </div>
          <div class="image-info-item">
            <span class="info-value dimension-info"></span>
          </div>
          <div class="image-info-item">
            <span class="info-value type-info"></span>
          </div>
        </div>
        
        <div class="image-preview-footer">
          <button class="nav-button image-preview-prev" title="上一张">
            ${SYMBOLS.ARROWS.LEFT}
          </button>
          <div class="image-preview-navigation-container">
            ${this.textInput.render()}
            <span class="navigation-total">/ ${this.previewElements.length}</span>
          </div>
          <button class="nav-button image-preview-next" title="下一张">
            ${SYMBOLS.ARROWS.RIGHT}
          </button>
        </div>
      </div>
    `)

    // 添加事件监听
    this.imagePreview.addPreviewEventListeners(previewElement)

    return previewElement
  }

  renderTextInput(): TextInput {
    return new TextInput({
      id: this.navigationInputId,
      type: 'text',
      placeholder: '',
      value: '1',
      onChange: async (value) => {
        const targetIndex = Number.parseInt(value as string, 10) - 1 // 转换为 0-based 索引

        // 验证输入
        if (Number.isNaN(targetIndex) || targetIndex < 0 || targetIndex >= this.previewElements.length) {
          this.showInputError()
          return
        }

        // 跳转到指定图片
        await this.imagePreview.jumpToIndex(targetIndex)
      },
    })
  }

  /**
   * 显示输入错误
   */
  private showInputError(): void {
    if (!this.currentPreviewElement)
      return

    const $input = this.currentPreviewElement.find(`#${this.navigationInputId}`)
    $input.addClass('error')

    // 2秒后隐藏错误
    setTimeout(() => {
      $input.removeClass('error')
      $input.val(this.currentPreviewIndex + 1)
    }, 2000)
  }

  /**
   * 更新预览内容（不重新创建容器）
   */
  updatePreviewContent(state: PreviewState): void {
    if (!this.currentPreviewElement)
      return

    const { imageUrl, title, path, imageInfo, downloaded = false, downloadTime = 0 } = state
    const { width, height, type, formattedSize } = imageInfo!

    // 更新标题和路径
    this.currentPreviewElement.find('.image-preview-title').text(title)
    this.currentPreviewElement.find('.image-preview-path').text(imageUrl)

    // 更新下载状态
    this.updateDownloadUI(downloaded, downloadTime)

    // 更新图片信息
    if (imageInfo) {
      this.currentPreviewElement.find('.path-info').text(path)
      this.currentPreviewElement.find('.dimension-info').text(`${width} × ${height} px`)
      this.currentPreviewElement.find('.type-info').text(type)
      this.currentPreviewElement.find('.size-info').text(formattedSize)
    }

    // 显示加载状态
    this.currentPreviewElement.find('.image-preview-loading').show()
    this.currentPreviewElement.find('.image-preview-img').hide()

    // 加载图片
    const $img = this.currentPreviewElement.find('.image-preview-img')
    $img.attr('src', imageUrl)
    $img.attr('alt', title)

    // 图片加载完成后的处理
    $img.off('load').on('load', () => {
      this.currentPreviewElement?.find('.image-preview-loading').hide()
      $img.show()
    })

    // 图片加载失败的处理
    $img.off('error').on('error', () => {
      this.currentPreviewElement?.find('.image-preview-loading').text('图片加载失败')
    })
  }

  /**
   * 更新下载状态
   */
  updateDownloadState(state: PreviewState, downloaded: boolean = true): void {
    state.downloaded = downloaded
    state.downloadTime = downloaded ? Date.now() : undefined

    if (this.currentPreviewElement && state === this.previewElements[this.currentPreviewIndex]) {
      this.updateDownloadUI(downloaded, state.downloadTime || 0)
    }
  }

  /**
   * 更新下载 UI
   */
  private updateDownloadUI(downloaded: boolean, downloadTime: number): void {
    const $title = this.currentPreviewElement?.find('.image-preview-title')

    if (!$title || !$title.length)
      return

    $title.toggleClass('downloaded', downloaded)
    this.stopDownloadTime($title)

    if (!downloaded)
      return

    this.updateDownloadTime($title, downloadTime)
  }

  /**
   * 更新下载时间
   */
  updateDownloadTime($element: JQuery<HTMLElement>, downloadTime: number): void {
    this.imagePreview.timerManager.createTimerTask({
      id: this.updateDownloadTimeTask.id,
      interval: this.updateDownloadTimeTask.interval,
      callback: () => {
        $element.attr('data-download-time', `下载时间: ${ToolKit.time.formatTime(downloadTime)}（${ToolKit.time.formatRelativeTime(downloadTime)}）`)
      },
    })
    this.updateDownloadTimeTask.running = true
  }

  /**
   * 停止更新下载时间
   */
  stopDownloadTime($element: JQuery<HTMLElement>): void {
    if (this.updateDownloadTimeTask.running) {
      this.imagePreview.timerManager.clearInterval(this.updateDownloadTimeTask.id)
      this.updateDownloadTimeTask.running = false
    }

    $element.removeAttr('data-download-time')
  }

  /**
   * 更新导航状态
   */
  updateNavigationState(): void {
    if (!this.currentPreviewElement)
      return

    const $prevBtn = this.currentPreviewElement.find('.image-preview-prev')
    const $nextBtn = this.currentPreviewElement.find('.image-preview-next')
    const $total = this.currentPreviewElement.find('.navigation-total')
    const $input = this.currentPreviewElement.find(`#${this.navigationInputId}`)

    if (this.previewElements.length > 1) {
      // 更新输入框值
      $input.val(this.currentPreviewIndex + 1)

      // 更新导航总数
      $total.text(`/ ${this.previewElements.length}`)

      // 更新按钮状态
      $prevBtn.prop('disabled', false)
      $nextBtn.prop('disabled', false)

      // 显示导航相关元素
      this.currentPreviewElement.find('.image-preview-prev, .image-preview-next, .image-preview-footer').show()
    }
    else {
      // 隐藏导航相关元素
      this.currentPreviewElement.find('.image-preview-prev, .image-preview-next, .image-preview-footer').hide()
    }
  }

  /**
   * 显示下载进度
   */
  showDownloadProgress(current: number, total: number): void {
    if (!this.currentPreviewElement)
      return

    const $progress = this.currentPreviewElement.find('.download-progress')
    if (!$progress.length) {
      const progressHtml = `
      <div class="download-progress">
        <div class="progress-bar">
          <div class="progress-fill"></div>
        </div>
        <div class="progress-text">下载中: ${current}/${total}</div>
      </div>
    `
      this.currentPreviewElement.append(progressHtml)
    }
    else {
      $progress.find('.progress-text').text(`下载中: ${current}/${total}`)
      $progress.find('.progress-fill').css('width', `${(current / total) * 100}%`)
    }
  }

  /**
   * 隐藏下载进度
   */
  hideDownloadProgress(): void {
    this.currentPreviewElement?.find('.download-progress').remove()
  }

  /**
   * 移除所有预览按钮
   */
  removeAllPreviewButtons(): void {
    $(`.${this.buttonClassName}`).remove()
  }

  /**
   * 移除所有预览按钮
   */
  private removeAllPreviewButtonsStatus(): void {
    $(`.${this.buttonClassName}`).removeClass('active')
  }

  /**
   * 移除图片预览
   */
  removePreview(): void {
    if (this.currentPreviewElement) {
      this.currentPreviewElement.remove()
      this.currentPreviewElement = null
    }

    // 清除预览元素引用
    this.imagePreview.previewStates.forEach((state) => {
      state.previewElement = null
    })

    this.removeAllPreviewButtonsStatus()
  }

  getStyles(): string {
    const minSize = this.imagePreview.config.minPreviewSize || 100

    return `
.${this.targetClassName} {
  cursor: pointer;
  
  &:hover {
    .${this.buttonClassName} {
      opacity: 1;
    }
  }
  
  .${this.buttonClassName} {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    background: transparent;
    border: none;
    font-size: 12px;
    opacity: 0;
    cursor: pointer;
    transition: all 0.2s ease;
    
    &.active {
      opacity: 1;
    }

    &:hover, &.active {
      &::before {
        ${this.imagePreview.stylesService.inlinePseudo.setIconMask({
          color: ICON_COLOR.hover,
        })}
      }
    }
    
    &::before {
      ${this.imagePreview.stylesService.inlinePseudo.iconMask({
        backgroundImageId: ICON_IDS.action.view,
      })}
    }
  }
}

.${this.className} {
  position: fixed;
  z-index: 99999;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80%;
  max-width: 90vw;
  height: 80%;
  max-height: 90vh;
  min-width: ${minSize}px;
  background: white;
  border-radius: 12px;
  box-shadow: 
    0 20px 40px rgba(0, 0, 0, 0.1),
    0 0 0 100vmax rgba(0, 0, 0, 0.5);
  border: 1px solid #e0e0e0;
  animation: imagePreviewFadeIn 0.2s ease;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  
  .image-preview-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
    border-bottom: 1px solid #f0f0f0;
    background: #fafafa;
    flex-shrink: 0;
    
    .image-preview-title-group {
      flex: 1;
      min-width: 0;
      
      .image-preview-title {
        position: relative;
        display: inline-flex;
        align-items: center;
        margin: 0 0 4px 0;
        max-width: 100%;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 16px;
        font-weight: 600;
        color: #333;
        
        &.downloaded::after {
          content: '已下载';
          position: absolute;
          top: 50%;
          left: 100%;
          transform: translateY(-50%);
          background: #4caf50;
          color: white;
          margin-left: 8px;
          padding: 2px 6px;
          border-radius: 10px;
          font-size: 10px;
          font-weight: 500;
          white-space: nowrap;
          z-index: 1;
        }
        
        &.downloaded:hover::after {
          content: attr(data-download-time);
          background: #2196f3;
        }
      }
      
      .image-preview-path {
        font-size: 12px;
        color: #666;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
    
    .image-preview-toolbar {
      display: flex;
      gap: 8px;
      align-items: center;
      
      button {
        background: rgba(0, 0, 0, 0.7);
        color: white;
        border: none;
        border-radius: 6px;
        width: 36px;
        height: 36px;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 14px;
        transition: all 0.2s ease;
        
        &:hover:not(:disabled) {
          background: rgba(0, 0, 0, 0.8);
          transform: scale(1.05);
        }
        
        &:disabled {
          opacity: 0.3;
          cursor: not-allowed;
        }
      }
      
      .image-preview-close:hover {
        color: #F44336;
      }
    }
  }
  
  .image-preview-content {
    flex: 1;
    display: flex;
    overflow: hidden;
    
    .image-preview-image-container {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      overflow: hidden;
      padding: 20px;
      
      .image-preview-img {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
        transition: opacity 0.3s ease;
      }
      
      .image-preview-loading {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: #666;
        font-size: 14px;
      }
    }
  }
  
  /* 左下角：路径信息 */
  .image-preview-path-container {
    position: absolute;
    bottom: 10px;
    left: 20px;
    background: #fafafa;
    padding: 6px 12px;
    border-radius: 4px;
    font-size: 12px;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    
    .path-info {
      font-family: 'Monaco', 'Menlo', monospace;
    }
  }
  
  .image-preview-info {
    position: absolute;
    bottom: 10px;
    right: 20px;
    display: flex;
    gap: 8px;
    align-items: flex-end;
    
    .image-info-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 4px 6px;
      background: #fafafa;
      border-radius: 6px;
      border: 1px solid var(${this.imagePreview.themeVarService.default.border.colorPrimary});
      
      .info-label {
        font-weight: 500;
        color: #333;
        font-size: 13px;
      }
      
      .info-value {
        color: #666;
        font-size: 13px;
        font-family: 'Monaco', 'Menlo', monospace;
      }
    }
  }
  
  /* 下载进度 */
  .download-progress {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0, 0, 0, 0.8);
    color: white;
    padding: 15px 20px;
    border-radius: 8px;
    z-index: 1000;
    
    .progress-bar {
      width: 200px;
      height: 10px;
      background: #333;
      border-radius: 5px;
      overflow: hidden;
      margin-bottom: 8px;
      
      .progress-fill {
        height: 100%;
        background: #4caf50;
        transition: width 0.3s ease;
      }
    }
    
    .progress-text {
      text-align: center;
      font-size: 12px;
    }
  }
  
  .image-preview-footer {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 20px;
    gap: 10px;
    
    .image-preview-navigation-container {
      display: flex;
      align-items: center;
      padding: 0 8px;
      
      #${this.navigationInputId}, .navigation-total {
        font-size: 14px !important;
        color: #666 !important;
        font-weight: 500 !important;
        line-height: 20px !important;
      }
      
      #${this.navigationInputId} {
        border: none !important;
        width: 40px !important;
        text-align: right !important;
        font-family: auto !important;
        
        &.error {
          color: var(${this.imagePreview.themeVarService.message.error.textPrimary}) !important;
        }
      }
    }
    
    .nav-button {
      background: #fafafa;
      border: 1px solid var(${this.imagePreview.themeVarService.default.border.colorPrimary});
      border-radius: 6px;
      width: 36px;
      height: 36px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      cursor: pointer;
      transition: all 0.2s ease;
      
      &:hover:not(:disabled) {
        background: #e8e8e8;
        transform: scale(1.05);
      }
      
      &:disabled {
        opacity: 0.3;
        cursor: not-allowed;
      }
    }
  }
}
    `
  }
}
